
#include "codec/SkCodec.h"
#include "core/SkPath.h"
#include "core/SkImage.h"
#include "core/SkData.h"
#include "core/SkBitmap.h"
#include "core/SkPictureRecorder.h"
#include "effects/SkImageFilters.h"
#include "effects/SkBlurMaskFilter.h"
#include "effects/SkColorMatrix.h"
#include "effects/SkColorMatrixFilter.h"
#include "src/base/SkAutoMalloc.h"
#include "src/core/SkBitmapCache.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkTraceEventCommon.h"
#include "src/image/SkImage_Base.h"
#include "src/shaders/SkImageShader.h"
#include "testing/Testing.h"
#include "core/SkTileMode.h"
#include "utils/log.h"


static std::vector<sk_sp<SkImage>> gAllImages;
static std::vector<sk_sp<SkImage>> gAllSubImage;
static std::vector<sk_sp<SkImage>> gAllScaleImage;


static void load_all_skimage() {
    TRACE_EVENT0("skia", "load_all_skimage");
    int pic_num = Testing::GetInstance().getPicNum();
    int start_index = gAllImages.size();
    for (int i = start_index; i< pic_num; i++) {
        size_t length = 0;
        void* data = Testing::GetInstance().getPicData(&length, i);
        auto sk_data = SkData::MakeWithoutCopy(data, length);
        auto image = SkImages::DeferredFromEncodedData(sk_data);
        gAllImages.push_back(image);
        LOGI("load image data len %{public}ld %{public}p", length, data);
        
        if (i >= 5) {
            continue;
        }
        
        // load image
        SkBitmap bitmap;
        SkImageInfo info = SkImageInfo::Make(200, 200, image->imageInfo().colorType(), image->imageInfo().alphaType());
        bitmap.allocPixels(info);
        {
            TRACE_EVENT0("skia", "readPixels");
            image->readPixels(bitmap.pixmap(), 100, 100);
        }
        bitmap.setImmutable();
        auto sub_image = SkImages::RasterFromBitmap(bitmap);
        gAllSubImage.push_back(sub_image);
        
        auto raster_image = image->makeRasterImage();
        as_IB(raster_image)->getOHDrawingImage();
        
        // get scale bitmap
        SkBitmap bitmap_scale;
        info = SkImageInfo::Make(50, 50, raster_image->imageInfo().colorType(), raster_image->imageInfo().alphaType());
        bitmap_scale.allocPixels(info);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone));
        auto scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNearest));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kLinear));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        raster_image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        
        // get scale image
        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);

        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNearest)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kLinear)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);

        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
        assert(image->scalePixels(bitmap_scale.pixmap(), SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)));
        scale_image = SkImages::RasterFromBitmap(bitmap_scale);
        gAllScaleImage.push_back(scale_image);
        
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageRect, TEST_LEVEL::NORMAL, 800) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 200;

    load_all_skimage();

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);

    int pic_num = Testing::GetInstance().getPicNum();
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option1);
        start_X += width;
    }

    start_X = 0.f;
    start_Y += width;
    SkSamplingOptions option2(SkFilterMode::kNearest, SkMipmapMode::kLinear);
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option2);
        start_X += width;
    }
    
    start_X = 0.f;
    start_Y += width;
    SkSamplingOptions option3(SkFilterMode::kNearest, SkMipmapMode::kNone);
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option3);
        start_X += width;
    }
    
    start_X = 0.f;
    start_Y += width;

    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, 100, start_X + width, 100 + width},
                                  {start_X, start_Y, start_X + width, start_Y + width}, option1, nullptr,
                                  SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);
        start_X += width;
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImage, TEST_LEVEL::NORMAL, 3000) {
    float start_X = 0.f;
    float start_Y = 0.f;

    load_all_skimage();

    int pic_num = Testing::GetInstance().getPicNum();
    for (int i = 0; i < 3 && i < pic_num; i++) {
        test_canvas.drawImage(gAllImages[i], start_X, 0);
        start_X += gAllImages[i]->width();
        start_Y = fmax(start_Y, gAllImages[i]->height());
    }
    start_X = 0.f;
    int temp_Y = 0;
    for (int i = 3; i < 5 && i < pic_num; i++) {
        test_canvas.drawImage(gAllImages[i], start_X, start_Y);
        start_X += gAllImages[i]->width();
        temp_Y = fmax(temp_Y, gAllImages[i]->height());
        
    }
    start_Y += temp_Y;
    start_X = 0;
    temp_Y = 0;
    test_canvas.translate(0, start_Y);
    test_canvas.scale(0.2, 0.2);
    SkSamplingOptions option(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    for (int i = 5; i < 5 + 9 && i < pic_num; i++) {
        test_canvas.drawImageRect(
            gAllImages[i], {start_X, 0, start_X + gAllImages[i]->width(), 0.f + gAllImages[i]->height()}, option);
        temp_Y = fmax(temp_Y, gAllImages[i]->height());
        start_X += gAllImages[i]->width();
    }
    start_Y = temp_Y;
    start_X = 0;
    temp_Y = 0;
    test_canvas.translate(0, start_Y);
    for (int i = 5 + 9; i < 5 + 9 + 9 && i < pic_num; i++) {
        test_canvas.drawImageRect(
            gAllImages[i], {start_X, 0, start_X + gAllImages[i]->width(), 0.f + gAllImages[i]->height()}, option);
        temp_Y = fmax(temp_Y, gAllImages[i]->height());
        start_X += gAllImages[i]->width();
    }
    start_Y += temp_Y;

}


static sk_sp<SkImage> gNormalImage = nullptr;

static void create_normal_skimage() {
    TRACE_EVENT0("skia", "create_normal_skimage");
    if (gNormalImage) {
        return;
    }

    int numBytes = 256 * 256 * 4;

    SkAutoMalloc buffer(numBytes);

    unsigned char *data = (unsigned char *)buffer.get();
    for (int i = 0; i < 256; i++) {
        for (int j = 0; j < 256; j++) {
            data[(i + j * 256) * 4] = i;
            data[(i + j * 256) * 4 + 1] = j;
            data[(i + j * 256) * 4 + 2] = 255;
            data[(i + j * 256) * 4 + 3] = 255;
        }
    }
    auto sk_data = SkData::MakeFromMalloc(buffer.release(), numBytes);
    auto sk_image = SkImages::RasterFromData(SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kOpaque_SkAlphaType),
                                             sk_data, 256 * 4);
    gNormalImage = sk_image;
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageRaster, TEST_LEVEL::NORMAL, 300) {
    float start_X = 0.f;
    float start_Y = 0.f;

    create_normal_skimage();

    test_canvas.drawImage(gNormalImage, start_X, start_Y);

    start_X += 300.f;

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    test_canvas.drawImageRect(gNormalImage, {start_X, start_Y, start_X + 256, start_Y + 256}, option1);

    start_X += 300.f;
    test_canvas.drawImageRect(gNormalImage, {start_X, start_Y, start_X + 300, start_Y + 300}, option1);

}

static SkBitmap gNormalBitmap;
static SkBitmap gNormalPixmap;

static sk_sp<SkImage> gNormalBitmapImage[5];


static void create_normal_skbitmap() {
    TRACE_EVENT0("skia", "create_normal_skbitmap");
    if (!gNormalBitmap.empty()) {
        return;
    }    

    int numBytes = 256 * 256 * 4;

    gNormalBitmap.allocPixels(SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
 
    unsigned char *data = (unsigned char *)gNormalBitmap.getPixels();
    for (int i = 0; i < 256; i++) {
        for (int j = 0; j < 256; j++) {
            data[(i + j * 256) * 4] = i;
            data[(i + j * 256) * 4 + 1] = j;
            data[(i + j * 256) * 4 + 2] = 0;
            data[(i + j * 256) * 4 + 3] = 255;
        }
    }

    gNormalBitmapImage[0] = SkImages::RasterFromBitmap(gNormalBitmap);

    gNormalBitmap.setImmutable();

    gNormalBitmapImage[1] = SkImages::RasterFromBitmap(gNormalBitmap);

    gNormalBitmapImage[2] = SkImages::RasterFromPixmapCopy(gNormalBitmap.pixmap());

    for (int i = 0; i < 256; i++) {
        for (int j = 0; j < 256; j+=2) {
            data[(i + j * 256) * 4 + 1] = 255;
        }
    }

    gNormalBitmapImage[3] = SkImages::RasterFromBitmap(gNormalBitmap);
    gNormalBitmapImage[4] = SkImages::RasterFromPixmap(gNormalBitmap.pixmap(), {}, nullptr);
}



DEF_TEST_CANVAS_WITH_HEIGHT(drawImageWithShader, TEST_LEVEL::NORMAL, 400) {
    float start_X = 0.f;
    float start_Y = 0.f;

    create_normal_skimage();
    create_normal_skbitmap();

    // ImageShader is very inefficient on the current version of OHOS.
    SkPaint paint;

    // Caching the shader does not improve performance.
    {
        TRACE_EVENT0("skia", "DrawRectWithImageShader-RasterImage");

        SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
        auto shader1 = gNormalImage->makeShader(SkTileMode::kClamp, SkTileMode::kDecal, option1, nullptr);
        paint.setShader(shader1);
        test_canvas.drawRect({start_X, start_Y, start_X + 350, start_Y + 350}, paint);
        start_X += 400.f;
    }
    {
        TRACE_EVENT0("skia", "DrawRectWithImageShader-Bitmap");

        SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
        auto shader1 = gNormalBitmap.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, option1, nullptr);
        paint.setShader(shader1);
        test_canvas.drawRect({start_X, start_Y, start_X + 350, start_Y + 350}, paint);
        start_X += 400.f;
    }

    if (gAllImages.size() > 0) {
        TRACE_EVENT0("skia", "DrawRectWithImageShader-OHImage");
        SkSamplingOptions option2(SkFilterMode::kNearest, SkMipmapMode::kNearest);
        SkMatrix scale = SkMatrix::RectToRect(SkRect::MakeWH(100, 100), SkRect::MakeWH(50, 150));
        auto shader2 = gAllImages[0]->makeShader(SkTileMode::kMirror, SkTileMode::kRepeat, option2, scale);
        paint.setShader(shader2);
        test_canvas.drawRect({start_X, start_Y, start_X + 350, start_Y + 350}, paint);
        start_X += 400.f;
    }

}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageWithRead, TEST_LEVEL::NORMAL, 220) {
    load_all_skimage();
    float start_X = 0.f;
    float start_Y = 0.f;

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    if (gAllSubImage.size() > 0) {
        test_canvas.drawImageRect(gAllSubImage[0], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
    }
    start_X += 220.f;
    
    if (gAllSubImage.size() > 1) {
        test_canvas.drawImageRect(gAllSubImage[1], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
    }
    start_X += 220.f;

    if (gAllSubImage.size() > 2) {
        test_canvas.drawImageRect(gAllSubImage[2], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
    }
    start_X += 220.f;

    if (gAllSubImage.size() > 3) {
        test_canvas.drawImageRect(gAllSubImage[3], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
    }
    start_X += 220.f;

    if (gAllSubImage.size() > 4) {
        test_canvas.drawImageRect(gAllSubImage[4], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
    }
    start_X += 220.f;

}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageWithScaleBitmap, TEST_LEVEL::NORMAL, 1200) {
    load_all_skimage();
    float start_X = 0.f;
    float start_Y = 0.f;

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);

    for (int i = 0; i < gAllScaleImage.size(); i++) {
        test_canvas.drawImageRect(gAllScaleImage[i], {start_X, start_Y, start_X + 200, start_Y + 200}, option1);
        start_Y += 200.f;
        if (i % 6 == 5) {
            start_Y = 0.f;
            start_X += 200.f;
        }
    }

}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageWithBitmapPixmap, TEST_LEVEL::NORMAL, 300) {
    create_normal_skbitmap();
    float start_X = 0.f;
    float start_Y = 0.f;

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    test_canvas.drawImageRect(gNormalBitmapImage[0], {start_X, start_Y, start_X + 256, start_Y + 256}, option1);
    start_X += 300.f;
    
    test_canvas.drawImageRect(gNormalBitmapImage[1], {start_X, start_Y, start_X + 256, start_Y + 256}, option1);
    start_X += 300.f;

    test_canvas.drawImageRect(gNormalBitmapImage[2], {start_X, start_Y, start_X + 256, start_Y + 256}, option1);
    start_X += 300.f;

    test_canvas.drawImageRect(gNormalBitmapImage[3], {start_X, start_Y, start_X + 256, start_Y + 256}, option1);
    start_X += 300.f;

    test_canvas.drawImageRect(gNormalBitmapImage[4], {start_X, start_Y, start_X + 256, start_Y + 256}, option1);
    start_X += 300.f;

}



sk_sp<SkPicture> gSkPicture = nullptr;

static void createSkPicture() {
    if (gSkPicture) {
        return;
    }
    SkPictureRecorder recorder;
    SkCanvas* recordCanvas = recorder.beginRecording(1000, 400);
    TestCanvas_drawImageWithShader(*recordCanvas);
    gSkPicture = recorder.finishRecordingAsPicture();
    
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawPictureWithShader, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(200, 200, 200));
    // draw TestCanvas_drawImageWithShader
    // draw ImageShader using Picture can improve performance.
    test_canvas.drawPicture(gSkPicture);
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawImageRectWithImageFilter, TEST_LEVEL::NORMAL, 1000) {
    float start_X = 0.f;
    float start_Y = 20.f;
    float width = 180;

    load_all_skimage();
    test_canvas.clear(SK_ColorRED);

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    SkPaint paint;
    
    // 裁剪范围限定左上角
    SkImageFilters::CropRect crop(SkRect::MakeXYWH(0, 0, 100, 100));

    // 创建带裁剪的 Blur filter
    auto blurFilter = SkImageFilters::Blur(15.0f, 15.0f, SkTileMode::kDecal, nullptr, crop);

    paint.setImageFilter(blurFilter);

    int pic_num = Testing::GetInstance().getPicNum();
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option1, &paint);
        start_X += 200;
        if (i == 0) {
            blurFilter = SkImageFilters::Blur(15.0f, 15.0f, SkTileMode::kDecal, nullptr);
            paint.setImageFilter(blurFilter);
        }
    }
    LOGI("SkImageFilters::Blur canComputeFastBounds %{public}d", paint.canComputeFastBounds());


    sk_sp<SkMaskFilter> blurFilter1 = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 20.0f);
    paint.setImageFilter(nullptr);
    paint.setMaskFilter(blurFilter1);
    LOGI("SkMaskFilter::MakeBlur canComputeFastBounds %{public}d", paint.canComputeFastBounds());

    start_X = 0.f;
    start_Y += 190;
    SkSamplingOptions option2(SkFilterMode::kNearest, SkMipmapMode::kLinear);
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option2, &paint);
        start_X += 200;
    }


    SkColorMatrix matrix;
    // enhance green
    matrix.setScale(0.5f, 2.0f, 1.0f, 1.0f);
    sk_sp<SkColorFilter> color_filter1 = SkColorFilters::Matrix(matrix);

    auto imageFilterColor = SkImageFilters::ColorFilter(color_filter1, nullptr);
    paint.setImageFilter(imageFilterColor);
    paint.setMaskFilter(nullptr);
    LOGI("SkImageFilters::ColorFilter canComputeFastBounds %{public}d", paint.canComputeFastBounds());

    start_X = 0.f;
    start_Y += 190;
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option2, &paint);
        start_X += 200;
    }

    sk_sp<SkColorFilter> lightFilter =
        SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(200, 200, 200), SkColorSetRGB(0, 128, 0));

    auto imageFilter2 = SkImageFilters::ColorFilter(lightFilter, SkImageFilters::Blur(15.0f, 15.0f, SkTileMode::kDecal, nullptr));
    paint.setImageFilter(imageFilter2);
    paint.setMaskFilter(nullptr);
    LOGI("SkImageFilters::ColorFilter whth blur canComputeFastBounds %{public}d", paint.canComputeFastBounds());

    start_X = 0.f;
    start_Y += 190;
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option2, &paint);
        start_X += 200;
    }

    auto imageFilter3 = SkImageFilters::Blur(15.0f, 15.0f, SkTileMode::kDecal, SkImageFilters::ColorFilter(lightFilter, nullptr));
    paint.setImageFilter(imageFilter3);
    paint.setMaskFilter(nullptr);

    LOGI("SkImageFilters::Blur whth ColorFilter canComputeFastBounds %{public}d", paint.canComputeFastBounds());

    start_X = 0.f;
    start_Y += 190;
    for (int i = 0; i < pic_num && i < 6; i++) {
        test_canvas.drawImageRect(gAllImages[i], {start_X, start_Y, start_X + width, start_Y + width}, option2, &paint);
        start_X += 200;
    }

    // don't support these
    auto filter1 = SkImageFilters::Compose(nullptr, nullptr);
    SkImageFilters::CropRect cropRect;
    auto filter2 = SkImageFilters::DropShadow(1, 1, 1, 1, SK_ColorRED, nullptr, cropRect);
}

DEF_TEST_CANVAS(drawImageFilterWithOffset, TEST_LEVEL::NORMAL) {
    auto blurFilter = SkImageFilters::Blur(20.0f, 20.0f, nullptr);
    auto offsetBlur = SkImageFilters::Offset(50.0f, 50.0f, std::move(blurFilter));
    
    SkPaint shadowPaint;
    auto rect = SkRect::MakeXYWH(100, 100, 200, 100);
    shadowPaint.setImageFilter(offsetBlur);

    shadowPaint.setColor(SK_ColorGRAY); // 阴影颜色
    test_canvas.drawRect(rect, shadowPaint);  // 阴影

    SkPaint originalPaint;
    test_canvas.drawRect(rect, originalPaint); // 原图
}


static std::vector<std::unique_ptr<SkCodec>> gAllImageCodec;
static std::vector<long> gImageCodecLastTime;
static std::vector<int> gImageFrameIndex;
static std::vector<sk_sp<SkImage>> gCodecImages;

static void load_all_codec() {
    TRACE_EVENT0("skia", "load_all_codec");
    int pic_num = Testing::GetInstance().getGifNum();
    int start_index = gAllImageCodec.size();
    for (int i = start_index; i< pic_num; i++) {
        size_t length = 0;
        void* data = Testing::GetInstance().getGifData(&length, i);
        auto sk_data = SkData::MakeWithoutCopy(data, length);
        auto codec = SkCodec::MakeFromData(sk_data);
        SkDebugf("Gif %d loop num: %d", i, codec->getRepetitionCount());
        gAllImageCodec.push_back(std::move(codec));
        gImageCodecLastTime.push_back(0);
        gImageFrameIndex.push_back(0);
        gCodecImages.push_back(nullptr);
    }
}

static void load_all_codec_images() {
    int gif_num = Testing::GetInstance().getGifNum();
    long now =
        std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
            .count();
    for (int i = 0; i < gif_num; i++) {
        int frameCount = gAllImageCodec[i]->getFrameCount();
        SkCodec::FrameInfo info;
        gAllImageCodec[i]->getFrameInfo(gImageFrameIndex[i], &info);
        if (info.fDuration < now - gImageCodecLastTime[i]) {
            SkCodec::Options opts;
            opts.fFrameIndex = gImageFrameIndex[i];
            auto [image, result] = gAllImageCodec[i]->getImage(gAllImageCodec[i]->getInfo(), &opts);
            if (image == nullptr) {
                LOGE("error get image");
            }
            gCodecImages[i] = image;
            gImageCodecLastTime[i] = now;
            if (gImageFrameIndex[i] == frameCount - 1) {
                gImageFrameIndex[i] = 0;
            } else {
                gImageFrameIndex[i]++;
            }
        }
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawGifImageRect, TEST_LEVEL::NORMAL, 800) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 800;

    load_all_codec();
    
    load_all_codec_images();

    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);

    int gif_num = Testing::GetInstance().getGifNum();
    for (int i = 0; i < gif_num; i++) {
        if (gCodecImages[i] == nullptr) {
            start_X += width;
            continue;
        }
        // When the target size of drawImage is larger than the original image size, mipmaps will not be enabled.
        // Otherwise, mipmaps will be enabled to provide better scaling effects, but this will also result in higher GPU
        // cycles
        test_canvas.drawImageRect(gCodecImages[i], {start_X, start_Y, start_X + width, start_Y + 800}, option1);
        start_X += width;
    }
}

static std::vector<sk_sp<SkImage>> gAllPixelmapImages;

static void load_all_pixelmap_image() {
    TRACE_EVENT0("skia", "load_all_pixelmap_image");
    int pic_num = Testing::GetInstance().getPixelmapNum();
    int start_index = gAllPixelmapImages.size();
    for (int i = start_index; i< pic_num; i++) {
        auto image = SkImages::DeferredFromOHPixelmap(Testing::GetInstance().getPixelmapData(i));
        gAllPixelmapImages.push_back(image);
    }
}


DEF_TEST_CANVAS_WITH_HEIGHT(drawPixelmapImageRect, TEST_LEVEL::NORMAL, 400) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 400;

    load_all_pixelmap_image();
    
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    
    for (auto image: gAllPixelmapImages) {
        test_canvas.drawImageRect(image, {start_X, start_Y, start_X + width, start_Y + 400}, option1);
        start_X += width;
    }
}



DEF_TEST_CANVAS_WITH_HEIGHT(drawAlphaImageShader, TEST_LEVEL::NORMAL, 1000) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 400;

    load_all_codec();
    
    load_all_codec_images();
    
    SkPaint paint;
    
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    auto shader1 = gCodecImages[1]->makeShader(SkTileMode::kClamp, SkTileMode::kDecal, option1, nullptr);
    paint.setShader(shader1);
    test_canvas.drawRect({0, 0, 1000, 1000}, paint);
}

DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestDrawPictureBig, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    load_all_skimage();
    
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kNone);
    
    SkSamplingOptions option2(SkFilterMode::kLinear, SkMipmapMode::kNearest);
    
    SkSamplingOptions option3(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    
    SkSamplingOptions option4(SkFilterMode::kNearest, SkMipmapMode::kNone);

    SkSamplingOptions option5(SkFilterMode::kNearest, SkMipmapMode::kNearest);
    
    SkSamplingOptions option6(SkFilterMode::kNearest, SkMipmapMode::kLinear);
    
    paint.setBlendMode(SkBlendMode::kSrc);
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option1, &paint);
        }
        case 1: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option2, &paint);
        }
        case 2: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option3, &paint);
        }
        case 3: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option4, &paint);
        }
        case 4: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option5, &paint);
        }
        case 5: {
            test_canvas.drawImageRect(gAllImages[1], {0, 0, 2720, 1260}, option6, &paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 6;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestDrawBigPictureBig, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint, paint2;
    load_all_skimage();
    
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kNone);
    
    SkSamplingOptions option2(SkFilterMode::kLinear, SkMipmapMode::kNearest);
    
    SkSamplingOptions option3(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    
    SkSamplingOptions option4(SkFilterMode::kNearest, SkMipmapMode::kNone);

    SkSamplingOptions option5(SkFilterMode::kNearest, SkMipmapMode::kNearest);
    
    SkSamplingOptions option6(SkFilterMode::kNearest, SkMipmapMode::kLinear);
    
    SkSamplingOptions option;
    int nowTestCnt = gTesingCnt % 6;
    switch (nowTestCnt) {
        case 0:
        option = option1;
        break;
        case 1:
        option = option2;
        break;
        case 2:
        option = option3;
        break;
        case 3:
        option = option4;
        break;
        case 4:
        option = option5;
        break;
        case 5:
        option = option6;
        break;
    }
    option = option4;

    
    if (gTesingCnt % 12 < 6) {
        paint.setBlendMode(SkBlendMode::kSrcOver);
    } else {
        paint.setBlendMode(SkBlendMode::kSrc);
    }
    paint.setBlendMode(SkBlendMode::kSrcOver);

    paint2.setColor(SkColorSetARGB(128, 0, 128, 255));
    test_canvas.clear(SK_ColorWHITE);
    
    switch (drawCounter) {
        case 0: {
//            800, 500
//            test_canvas.drawImageRect(gAllImages[3], SkRect::MakeXYWH(0, 0, 800, 500), option, &paint);
//            test_canvas.drawRect({700, 400, 900, 600}, paint2);
            paint.setBlendMode(SkBlendMode::kSrcOver);
            test_canvas.drawImageRect(gAllImages[5], {0, 0, 2720, 1260}, option, &paint);
        }
        case 1: {
//            test_canvas.drawImageRect(gAllImages[3], SkRect::MakeXYWH(800, 500, 800, 500), option, &paint);
//            test_canvas.drawRect({700, 400, 900, 600}, paint2);
//            paint.setBlendMode(SkBlendMode::kSrc);
            test_canvas.drawImageRect(gAllImages[6], {0, 0, 2720, 1260}, option, &paint);
        }
        case 2: {
//            test_canvas.drawImageRect(gAllImages[3], SkRect::MakeXYWH(800, 0, 800, 500), option, &paint);
//            test_canvas.drawRect({700, 400, 900, 600}, paint2);
            paint.setBlendMode(SkBlendMode::kSrcOver);
            test_canvas.drawImageRect(gAllImages[7], {0, 0, 2720, 1260}, option, &paint);
        }
        case 3: {
//            test_canvas.drawImageRect(gAllImages[3], SkRect::MakeXYWH(800, 0, 800, 500), option, &paint);
//            test_canvas.drawRect({700, 400, 900, 600}, paint2);
//            paint.setBlendMode(SkBlendMode::kSrc);
            test_canvas.drawImageRect(gAllImages[8], {0, 0, 2720, 1260}, option, &paint);
        }case 4: {
//            test_canvas.drawImageRect(gAllImages[3], SkRect::MakeXYWH(800, 0, 800, 500), option, &paint);
//            test_canvas.drawRect({700, 400, 900, 600}, paint2);
            paint.setBlendMode(SkBlendMode::kSrcOver);
            test_canvas.drawImageRect(gAllImages[9], {0, 0, 2720, 1260}, option, &paint);
        }
        break;
    }
    drawCounter = (drawCounter + 1) % 5;
}




DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestDrawBigPictureShader, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint, paint2;
    paint2.setColor(SkColorSetARGB(128, 0, 128, 255));
    load_all_skimage();
    
    
    sk_sp<SkShader> shader;
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    static sk_sp<SkShader> shader1 = gAllImages[1]->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, option1, nullptr);
    static sk_sp<SkShader> shader2 = gAllImages[1]->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, option1, nullptr);
    static sk_sp<SkShader> shader3 = gAllImages[1]->makeShader(SkTileMode::kDecal, SkTileMode::kDecal, option1, nullptr);
    
    if (gTesingCnt % 6 < 2) {
        shader = shader1;
    } else if (gTesingCnt % 6 < 4) {
        shader = shader2;
    } else {
        shader = shader3;
        
    }
    paint.setShader(shader);
    
    int nowTestCnt = gTesingCnt % 6;
    
    if (gTesingCnt % 2 == 0) {
        paint.setBlendMode(SkBlendMode::kSrcOver);
    } else {
        paint.setBlendMode(SkBlendMode::kSrc);
    }

    test_canvas.clear(SK_ColorRED);
    
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 1: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 2: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 3: {
                test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
            }
        case 4: {
                test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
            }
        break;
    }
    
    drawCounter = (drawCounter + 1) % 5;
}




DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestDrawBlurPictureShader, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint, paint2;
    paint2.setColor(SkColorSetARGB(128, 0, 128, 255));
    load_all_skimage();
    
    
    SkSamplingOptions option1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    static sk_sp<SkShader> shader1 = gAllImages[1]->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, option1, nullptr);
    static sk_sp<SkShader> shader2 = gAllImages[1]->makeShader(SkTileMode::kDecal, SkTileMode::kDecal, option1, nullptr);
    
    auto blurFilter1 = SkImageFilters::Blur(15.0f, 15.0f, SkTileMode::kDecal, nullptr);
    auto blurFilter2 = SkImageFilters::Blur(30.0f, 30.0f, SkTileMode::kDecal, nullptr);
    paint.setShader(shader2);
    
    sk_sp<SkColorFilter> lightFilter =
        SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(200, 200, 200), SkColorSetRGB(0, 128, 0));
    if (gTesingCnt % 2 == 0) {
        auto blurFilter = SkImageFilters::Blur(5.0f, 5.0f, SkTileMode::kDecal, SkImageFilters::ColorFilter(lightFilter, nullptr));
        paint.setImageFilter(blurFilter);
    } else {
        auto blurFilter = SkImageFilters::ColorFilter(lightFilter, SkImageFilters::Blur(5.0f, 5.0f, SkTileMode::kDecal, nullptr));
        paint.setImageFilter(blurFilter);
    }
    
    
//    if (gTesingCnt % 6 == 0) {
//        auto blurFilter = SkImageFilters::Blur(1.0f, 1.0f, SkTileMode::kDecal, nullptr);
//        paint.setImageFilter(blurFilter);
//    } else if (gTesingCnt % 6 == 1) {
//        auto blurFilter = SkImageFilters::Blur(2.0f, 2.0f, SkTileMode::kDecal, nullptr);
//        paint.setImageFilter(blurFilter);
//    } else if (gTesingCnt % 6 == 2) {
//        auto blurFilter = SkImageFilters::Blur(3.0f, 3.0f, SkTileMode::kDecal, nullptr);
//        paint.setImageFilter(blurFilter);
//    } else if (gTesingCnt % 6 == 3) {
//        auto blurFilter = SkImageFilters::Blur(5.0f, 5.0f, SkTileMode::kDecal, nullptr);
//        paint.setImageFilter(blurFilter);
//    } else if (gTesingCnt % 6 == 4) {
//        auto blurFilter = SkImageFilters::Blur(10.0f, 10.0f, SkTileMode::kDecal, nullptr);
//        paint.setImageFilter(blurFilter);
//    } else if (gTesingCnt % 6 == 5) {
//        auto blurFilter = SkImageFilters::Blur(10.0f, 10.0f, SkTileMode::kRepeat, nullptr);
//        paint.setImageFilter(blurFilter);
//    }
    
    
    int nowTestCnt = gTesingCnt % 6;

    test_canvas.clear(SK_ColorRED);
    
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 1: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 2: {
            test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
        }
        case 3: {
                test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
            }
        case 4: {
                test_canvas.drawRect(SkRect::MakeXYWH(0, 0, 2720, 1260), paint);
            }
        break;
    }
    
    drawCounter = (drawCounter + 1) % 5;
}



DEF_TEST_CANVAS_WITH_HEIGHT(drawRenderNode, TEST_LEVEL::NORMAL, 1000) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 800;
    int node_num = Testing::GetInstance().getNodeNum();
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setColor(SK_ColorRED);
    test_canvas.drawRect({0, 0, 200 ,200}, paint);
    start_X += 100;
    start_Y += 50;
    if (node_num >= 1) {
        auto node = Testing::GetInstance().getExternalNode(0);
        test_canvas.drawRenderNode(node, {start_X, start_Y, start_X + width, start_Y + 950});
        start_X += width;
    }
    paint.setColor(SK_ColorBLUE);
    test_canvas.drawRect({start_X - 100, 0, start_X + 100 ,200}, paint);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(10);
    
    for (int i = 1; i < node_num; i++) {
        
        auto node = Testing::GetInstance().getExternalNode(i);
        test_canvas.drawRenderNode(node, {start_X, start_Y, start_X + width, start_Y + 950});
//        test_canvas.drawRect({start_X, start_Y, start_X + width, start_Y + 950}, paint);
        start_X += width;
    }

}


static std::vector<sk_sp<SkImage>> gAllEncodeImages;

static void encode_and_decode_images() {
    load_all_skimage();
    load_all_pixelmap_image();
    if (gAllImages.empty() || gAllPixelmapImages.empty()) return;

    sk_sp<SkImage> image1 = gAllImages[0];
    sk_sp<SkImage> image2 = gAllPixelmapImages[0];

    std::vector<sk_sp<SkImage>> inputImages = { image1, image2 };
    std::vector<int> qualityList = { 1, 50, 100 };
    if (gAllEncodeImages.size() >= 6) {
        return;
    }

    for (auto& img : inputImages) {
        for (int q : qualityList) {
            sk_sp<SkData> encoded = img->encodeToData(SkEncodedImageFormat::kJPEG, q);
            if (!encoded || encoded->size() == 0) continue;

            sk_sp<SkImage> decoded = SkImages::DeferredFromEncodedData(encoded);
            if (decoded) {
                gAllEncodeImages.push_back(decoded);
            }
        }
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawEncodeImageRect, TEST_LEVEL::NORMAL, 800) {
    float start_X = 0.f;
    float start_Y = 0.f;
    float width = 200;

    encode_and_decode_images();

    SkSamplingOptions samplingOption(SkFilterMode::kLinear, SkMipmapMode::kLinear);

    int img_num = static_cast<int>(gAllEncodeImages.size());
    int draw_count = std::min(img_num, 6);

    for (int i = 0; i < draw_count; i++) {
        test_canvas.drawImageRect(
            gAllEncodeImages[i],
            {start_X, start_Y, start_X + width, start_Y + width},
            samplingOption
        );
        start_X += width;
    }
}
